package com.youlai.boot.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.boot.common.exception.BusinessException;
import com.youlai.boot.core.security.util.SecurityUtils;
import com.youlai.boot.system.converter.SpotRecordConverter;
import com.youlai.boot.system.mapper.SpotRecordMapper;
import com.youlai.boot.system.model.entity.*;
import com.youlai.boot.system.model.form.SpotRecordForm;
import com.youlai.boot.system.model.query.SpotRecordQuery;
import com.youlai.boot.system.model.vo.SpotRecordExcelVO;
import com.youlai.boot.system.model.vo.SpotRecordVO;
import com.youlai.boot.system.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 出票数据服务实现类
 *
 * @author lwb
 * @since 2025-06-29 22:35
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class SpotRecordServiceImpl extends ServiceImpl<SpotRecordMapper, SpotRecord> implements SpotRecordService {

    private final SpotRecordConverter spotRecordConverter;

    private final SpotTravelService spotTravelService;

    private final SpotCategoryService spotCategoryService;

    private final DeptService deptService;

    private final SpotCountService spotCountService;

    /**
     * 获取出票数据分页列表
     *
     * @param queryParams 查询参数
     * @return {@link IPage<SpotRecordVO>} 出票数据分页列表
     */
    @Override
    public IPage<SpotRecordVO> getSpotRecordPage(SpotRecordQuery queryParams) {
        Page<SpotRecordVO> pageVO = this.baseMapper.getSpotRecordPage(
                new Page<>(queryParams.getPageNum(), queryParams.getPageSize()),
                queryParams
        );
        return pageVO;
    }

    /**
     * 获取出票数据表单数据
     *
     * @param id 出票数据ID
     * @return
     */
    @Override
    public SpotRecordForm getSpotRecordFormData(Long id) {
        return this.baseMapper.getSpotRecordFormData(id);
    }

    public static final String MES = "出票成功，【旅行社：%s】【分类名称：%s】【余票：%s】";

    /**
     * 新增出票数据
     *
     * @param formData 出票数据表单对象
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String saveSpotRecord(SpotRecordForm formData) {
        if (Objects.isNull(formData.getOutTime())) {
            formData.setOutTime(LocalDateTime.now());
        }
        SpotRecord entity = spotRecordConverter.toEntity(formData);
        fieldFill(entity);

        SpotTravel spotTravel = spotTravelService.getSpotTravel(entity.getDeptId(), entity.getCategoryId());
        if (Objects.isNull(spotTravel)) {
            SpotCategory spotCategory = spotCategoryService.getCategoryById(entity.getCategoryId());
            Dept dept = deptService.getDeptById(entity.getDeptId());
            throw new BusinessException(dept.getName() + "没有" + spotCategory.getName() + "的余票！请联系相关人员处理！");
        }
        if (spotTravel.getNum() < entity.getNum()) {
            String mes = spotTravel.getDeptName() + "的" + spotTravel.getCategoryName() + "余票不足，当前剩余：" + spotTravel.getNum() + "。";
            throw new BusinessException(mes);
        }
        log.info("{}的{}剩余票数：{}", spotTravel.getDeptName(), spotTravel.getCategoryName(), spotTravel.getNum());
        spotTravel.setNum(spotTravel.getNum() - entity.getNum());
        //减少当前旅行社对应分类的票
        spotTravelService.updateById(spotTravel);


        //增加当前出票记录
        LocalDateTime now = LocalDateTime.now();
        Long userId = SecurityUtils.getUserId();
        SpotCount spotCount = new SpotCount();
        spotCount.setDeptId(entity.getDeptId());
        spotCount.setDeptName(entity.getDeptName());
        spotCount.setCategoryId(entity.getCategoryId());
        spotCount.setCategoryName(entity.getCategoryName());
        spotCount.setUserId(SecurityUtils.getUserId());
        spotCount.setOperateType(1);
        spotCount.setNum(entity.getNum());
        spotCount.setOperateTime(entity.getOutTime());
        spotCount.setCreateBy(userId);
        spotCount.setCreateTime(now);
        spotCount.setUpdateBy(userId);
        spotCount.setUpdateTime(now);
        spotCountService.save(spotCount);
        this.save(entity);

        return String.format(MES, spotTravel.getDeptName(), spotTravel.getCategoryName(),spotTravel.getNum());
    }

    public void fieldFill(SpotRecord entity) {
        Long userId = SecurityUtils.getUserId();
        LocalDateTime now = LocalDateTime.now();
        if (entity.getId() == null) {
            entity.setCreateBy(userId);
            entity.setCreateTime(now);
            entity.setUpdateBy(userId);
            entity.setUpdateTime(now);
        } else {
            entity.setUpdateBy(userId);
            entity.setUpdateTime(now);
        }
    }

    /**
     * 更新出票数据
     *
     * @param id       出票数据ID
     * @param formData 出票数据表单对象
     * @return
     */
    @Override
    public boolean updateSpotRecord(Long id, SpotRecordForm formData) {
        if (Objects.isNull(formData.getOutTime())) {
            formData.setOutTime(LocalDateTime.now());
        }
        SpotRecord entity = spotRecordConverter.toEntity(formData);
        fieldFill(entity);
        return this.updateById(entity);
    }

    /**
     * 删除出票数据
     *
     * @param ids 出票数据ID，多个以英文逗号(,)分割
     * @return
     */
    @Override
    public boolean deleteSpotRecords(String ids) {
        Assert.isTrue(StrUtil.isNotBlank(ids), "删除的出票数据数据为空");
        // 逻辑删除
        List<Long> idList = Arrays.stream(ids.split(","))
                .map(Long::parseLong)
                .toList();
        return this.removeByIds(idList);
    }

    /**
     * 出票数据导出
     *
     * @param queryParams
     * @return
     */
    @Override
    public List<SpotRecordExcelVO> export(SpotRecordQuery queryParams) {
        List<SpotRecordExcelVO> list = this.baseMapper.exportList(queryParams);
        if (CollUtil.isNotEmpty(list)) {
            AtomicInteger index = new AtomicInteger(1);
            list.forEach(item -> item.setSn(String.valueOf(index.getAndIncrement())));
        }
        return list;
    }

    @Override
    public List<SpotRecordForm> getCount(SpotRecordQuery queryParams) {
        return this.baseMapper.getCount(queryParams);
    }
}
